package top.tangyh.lamp.care.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.tangyh.basic.exception.BizException;
import top.tangyh.lamp.care.entity.BHl7YzLisResult;
import top.tangyh.lamp.care.entity.BObsvRecord;
import top.tangyh.lamp.care.entity.BPatient;
import top.tangyh.lamp.care.entity.BPgRecord;
import top.tangyh.lamp.care.manager.BHl7YzLisResultManager;
import top.tangyh.lamp.care.manager.BObsvRecordManager;
import top.tangyh.lamp.care.manager.BPgRecordManager;
import top.tangyh.lamp.care.manager.BPgpfManager;
import top.tangyh.lamp.care.mapper.*;
import top.tangyh.lamp.care.service.ApachiiPickService;
import top.tangyh.lamp.care.vo.query.ApacheiiPickQueryInVO;
import top.tangyh.lamp.care.vo.result.*;
import top.tangyh.lamp.common.constant.CommonConstant;
import top.tangyh.lamp.common.properties.SystemProperties;
import top.tangyh.lamp.common.utils.ConvertUtil;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@AllArgsConstructor
@Slf4j
public class ApacheiiPickServiceImpl implements ApachiiPickService {
	private final BObsvRecordMapper bObsvRecordMapper;
	private final BPgpfManager pgpfMapper;
	private final BPgSrxDetailNormalMapper apacheiiPickMapper;
	private final BHl7YzLisResultMapper bHl7YzLisResultMapper;
	private final BPgRecordMapper bPgRecordMapper;
	private final BHl7MoveDetailMapper bHl7MoveDetailMapper;
    private  final BPatientMapper bPatientMapper;
	@Autowired
	protected SystemProperties systemProperties;

	/**
	 * 自动获取数据周期--apacheii评分
	 */
	private final static int CYCLE = 8;

	/**
	 * 查询方式--精确
	 */
	private final static String QUERY_TYPE_EQ = "eq";

	/**
	 * 查询方式--模糊
	 */
	private final static String QUERY_TYPE_LIKE = "like";

	/**
	 * 自动获取数据时， 在采集时间的的BEFORE_HOUR小时内采集
	 */
	private final static int BEFORE_HOUR = -24;


	/**
	 * 项目顺序映射，key--项目code, value--排序值
	 */
	private static Map<String, Integer> itemOrderMap = new LinkedHashMap<>();

	static {
		//肛温
		itemOrderMap.put("gcx_T", 1);
		//平均动脉压
		itemOrderMap.put("ibpM", 2);
		//心率
		itemOrderMap.put("ecg", 3);
		//呼吸
		itemOrderMap.put("resp", 4);
		//动脉血ph
		itemOrderMap.put("ph", 7);
		//血清钠
		itemOrderMap.put("na", 8);
		//血清钾
		itemOrderMap.put("k", 9);
		//血清肌酐
		itemOrderMap.put("jigan", 10);
		//红细胞压积
		itemOrderMap.put("hxbyj", 11);
		//白细胞计数
		itemOrderMap.put("bxbjs", 12);
		//白细胞计数
		itemOrderMap.put("hco3", 13);
		//医生Glasgow评分
		itemOrderMap.put("glasgow", 14);
	}

	/**
	 * 项目标题映射，key--项目code, value--排序值
	 */
	private static Map<String, String> itemTitleMap = new LinkedHashMap<>();

	static {
		itemTitleMap.put("gcx_T", "肛温（℃）");
		itemTitleMap.put("ibpM", "平均动脉压(mmHg)");
		itemTitleMap.put("ecg", "心率(次/分)");
		itemTitleMap.put("resp", "呼吸(次/分)");
		itemTitleMap.put("ph", "动脉血pH");
		itemTitleMap.put("na", "血清钠(mmol/L)");
		itemTitleMap.put("k", "血清钾(mmol/L)");
		itemTitleMap.put("jigan", "血清肌酐(μmol/L)\n" +
				"如有急性肾功能衰竭，加倍计分");
		itemTitleMap.put("hxbyj", "红细胞压积");
		itemTitleMap.put("bxbjs", "白细胞计数(×10^9 /L)");
		itemTitleMap.put("hco3", "如无动脉血气分析，测静脉血\n" +
				"HCO3(mmol/L)");
		itemTitleMap.put("glasgow", "Glasgow昏迷评分");
	}

	/**
	 * 检验报告查询映射，key--项目code, value--检验值
	 */
	private static Map<String, JianYanHelpEntity> jyQueryValMap = new LinkedHashMap<>();

	static {
		jyQueryValMap.put("ph", new JianYanHelpEntity("血液酸碱度（PH）", QUERY_TYPE_LIKE));
		jyQueryValMap.put("na", new JianYanHelpEntity("钠", QUERY_TYPE_LIKE));
		jyQueryValMap.put("k", new JianYanHelpEntity("钾", QUERY_TYPE_LIKE));
		jyQueryValMap.put("jigan", new JianYanHelpEntity("肌酐", QUERY_TYPE_LIKE));
		jyQueryValMap.put("hxbyj", new JianYanHelpEntity("红细胞压积", QUERY_TYPE_LIKE));
		jyQueryValMap.put("bxbjs", new JianYanHelpEntity("白细胞计数", QUERY_TYPE_LIKE));
		jyQueryValMap.put("hco3", new JianYanHelpEntity("实际碳酸氢根（AB）", QUERY_TYPE_EQ));
	}

	/**
	 * 观察项标识有序集合
	 */
	private static LinkedHashSet<String> gcxSet = Stream.of("gcx_T", "ibpM", "ecg", "resp").collect(Collectors.toCollection(LinkedHashSet::new));


	@Override
	public ApacheiiPickVO apcciiPick(ApacheiiPickQueryInVO param) {
//		Long testStart = System.currentTimeMillis();

		ApacheiiPickVO rst = new ApacheiiPickVO();
		if (param == null || StrUtil.isBlank(param.getHospitalNumber())) {
			throw new BizException("住院号不能为空");
		}
		//获得入科时间列表;
		List<Date> rkTimeList = getRkTimeList(rst, param.getHospitalNumber());
		if (CollectionUtil.isEmpty(rkTimeList)) {
			return rst;
		}

		rst.setHospitalNumber(param.getHospitalNumber());
		List<ApacheiiPickTimeVO> mappedlist = new ArrayList<>();
		rst.setList(mappedlist);
		for (Date mappedDate : rkTimeList) {
			if (mappedDate == null) {
				continue;
			}
			ApacheiiPickTimeVO apacheiiPickTimeVO = new ApacheiiPickTimeVO();
			mappedlist.add(apacheiiPickTimeVO);
			apacheiiPickTimeVO.setMappedTime(mappedDate.getTime());
			List<ApacheiiPickDetailVO> pickDetailList = new ArrayList<>();
			apacheiiPickTimeVO.setList(pickDetailList);
			long startTime = DateUtil.offsetHour(mappedDate, BEFORE_HOUR).getTime();
			long endTime = mappedDate.getTime();
			//处理观察项
			pickObsvV1(pickDetailList, param.getHospitalNumber(), startTime, endTime);
			//处理检验报告
			pickJianV1(pickDetailList, param.getHospitalNumber(), startTime, endTime);
			//处理Glasgow昏迷评分
			pickGlasgow(pickDetailList, param.getHospitalNumber(), startTime, endTime);

		}
		return rst;
	}

	/**
	 * 获取apacheii评分数据---Glasgow昏迷评分
	 *
	 * @param pickDetailList
	 * @param hospitalNumber
	 * @param startTime
	 * @param endTime
	 */
	private void pickGlasgow(List<ApacheiiPickDetailVO> pickDetailList, String hospitalNumber, long startTime, long endTime) {
		//Glasgow昏迷评分 在通用评估评分配置中的id值;
		int glasgowTypeVal = 15;
		String glasgowCode = "glasgow";
		String type = "glasgow";

		ApacheiiPickDetailVO apacheiiPickDetailVO = new ApacheiiPickDetailVO();
		pickDetailList.add(apacheiiPickDetailVO);
		apacheiiPickDetailVO.setItemCode(glasgowCode);
		apacheiiPickDetailVO.setItemType(type);
		apacheiiPickDetailVO.setItemName(itemTitleMap.get(glasgowCode));
		apacheiiPickDetailVO.setOrderNo(itemOrderMap.get(glasgowCode));

		LambdaQueryWrapper<BPgRecord> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BPgRecord::getHospitalNumber, hospitalNumber)
				.eq(BPgRecord::getPgId, glasgowTypeVal)
				.between(BPgRecord::getGradeTime, new Date(startTime), new Date(endTime));
		List<BPgRecord> yxPgRecordList = bPgRecordMapper.selectList(queryWrapper);
		if (CollectionUtil.isEmpty(yxPgRecordList)) {
			return;
		}
		List<String> list = new ArrayList<>();
		List<ApacheiiPickPgVO> pgDetailVOList = new ArrayList<>();

		Integer minVal =Integer.MAX_VALUE;
		ApacheiiPickPgVO pgDetailVO = new ApacheiiPickPgVO();
		pgDetailVOList.add(pgDetailVO);
		for (BPgRecord item : yxPgRecordList) {
			Integer showVal = Convert.toInt(item.getShowValue());
            if(showVal<minVal){
				minVal=showVal;
				pgDetailVO.setScore(item.getShowValue());
				pgDetailVO.setPgRecordId(Convert.toStr(item.getId()));
				pgDetailVO.setNormalDetailList(apacheiiPickMapper.findPgDetail(Convert.toStr(item.getId())));
			}
		}
		list.add(Convert.toStr(minVal));
		apacheiiPickDetailVO.setPgDetailList(pgDetailVOList);
		apacheiiPickDetailVO.setItemValueList(list);

	}


	/**
	 * 获取apacheii评分数据---检验报表
	 *
	 * @param pickDetailList
	 * @param hospitalNumber
	 * @param startTime
	 * @param endTime
	 */
	private void pickJianV1(List<ApacheiiPickDetailVO> pickDetailList, String hospitalNumber, long startTime, long endTime) {
		String type = "jy";
		List<ApacheiiPickJianYanDetailVO> jianyanList = getJianYan(hospitalNumber, startTime, endTime);
		Map<String, List<ApacheiiPickJianYanDetailVO>> jianyanMap = new HashMap<>();
		for (ApacheiiPickJianYanDetailVO jyRd : jianyanList) {
			String reportName = jyRd.getReportName();
			if (StrUtil.isBlank(reportName)) {
				continue;
			}
			String itemCode = "";
			if (jyRd.getProjectName().contains("血液酸碱度（PH）")) {
				itemCode = "ph";
			} else if (jyRd.getProjectName().contains("钠")) {
				itemCode = "na";
			} else if (jyRd.getProjectName().contains("钾")) {
				itemCode = "k";
			} else if (jyRd.getProjectName().contains("肌酐")) {
				itemCode = "jigan";
			} else if (jyRd.getProjectName().contains("红细胞压积")) {
				itemCode = "hxbyj";
			} else if (jyRd.getProjectName().contains("白细胞计数")) {
				itemCode = "bxbjs";
			} else if (jyRd.getProjectName().contains("实际碳酸氢根（AB）")) {
				itemCode = "hco3";
			}
			List<ApacheiiPickJianYanDetailVO> jianyanItemList = jianyanMap.get(itemCode);
			if (jianyanItemList == null) {
				jianyanItemList = new ArrayList<>();
				jianyanMap.put(itemCode, jianyanItemList);
			}
			jianyanItemList.add(jyRd);
		}

		for (Map.Entry<String, List<ApacheiiPickJianYanDetailVO>> item : jianyanMap.entrySet()) {
			ApacheiiPickDetailVO apacheiiPickDetailVO = new ApacheiiPickDetailVO();
			pickDetailList.add(apacheiiPickDetailVO);
			String itemCode = item.getKey();
			apacheiiPickDetailVO.setItemCode(itemCode);
			apacheiiPickDetailVO.setItemType(type);
			apacheiiPickDetailVO.setItemName(itemTitleMap.get(itemCode));
			apacheiiPickDetailVO.setOrderNo(itemOrderMap.get(itemCode));
			apacheiiPickDetailVO.setJianyanList (item.getValue());
		}

	}

	/**
	 * 获取检验报告结果
	 *
	 * @param hospitalNumber 住院号
	 * @param startTime      查询开始时间
	 * @param endTime        查询结束时间
	 * @return
	 */
	private List<ApacheiiPickJianYanDetailVO> getJianYan(String hospitalNumber, long startTime, long endTime) {
		LambdaQueryWrapper<BHl7YzLisResult> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BHl7YzLisResult::getHospitalNumber, hospitalNumber)
				.between(BHl7YzLisResult::getTakeTime, new Date(startTime), new Date(endTime));

		queryWrapper.and(wrapper -> {
			for (String itemCode : jyQueryValMap.keySet()) {
				JianYanHelpEntity hlpEntity = jyQueryValMap.get(itemCode);
				if (JianYanHelpEntity.QUERY_TYPE_LIKE.equals(hlpEntity.getQueryType())) {
					wrapper.or().like(BHl7YzLisResult::getProjectName, hlpEntity.getSearchValue());
				} else {
					wrapper.or().eq(BHl7YzLisResult::getProjectName, hlpEntity.getSearchValue());
				}
			}
		});

		List<BHl7YzLisResult> listResultPOList = bHl7YzLisResultMapper.selectList(queryWrapper);
		return ConvertUtil.convertList(listResultPOList, ApacheiiPickJianYanDetailVO.class);
	}


	/**
	 * 获取apacheii评分数据---观察项记录
	 *
	 * @param pickDetailList
	 * @param hospitalNumber
	 * @param startTime
	 * @param endTime
	 */
	private void pickObsvV1(List<ApacheiiPickDetailVO> pickDetailList, String hospitalNumber, long startTime, long endTime) {
		String type = "gcx";
		List<BObsvRecord> list = getObsvRecordV1(hospitalNumber, startTime, endTime);
		Map<String, List<String>> itemValueMap = new HashMap<>();
		for (BObsvRecord rd : list) {
			String obsvCode = rd.getObsvCode();
			List<String> itemValueList = itemValueMap.get(obsvCode);
			if (itemValueList == null) {
				itemValueList = new ArrayList<>();
				itemValueMap.put(obsvCode, itemValueList);
			}

			itemValueList.add(rd.getPropValue() );
		}
		for(Map.Entry<String, List<String>> item: itemValueMap.entrySet()){
			ApacheiiPickDetailVO apacheiiPickDetailVO = new ApacheiiPickDetailVO();
			pickDetailList.add(apacheiiPickDetailVO);
			String obsvCode=item.getKey();
			apacheiiPickDetailVO.setItemCode(obsvCode);
			apacheiiPickDetailVO.setItemType(type);
			apacheiiPickDetailVO.setItemName(itemTitleMap.get(obsvCode));
			apacheiiPickDetailVO.setOrderNo(itemOrderMap.get(obsvCode));
			apacheiiPickDetailVO.setItemValueList(item.getValue());
		}
	}

	/**
	 * 获取观察项数据
	 *
	 * @param hospitalNumber
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	private List<BObsvRecord> getObsvRecordV1(String hospitalNumber, long startTime, long endTime) {
		BPatient patientPO =bPatientMapper.selectOneByHospitalNumber(hospitalNumber);
		LambdaQueryWrapper<BObsvRecord> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BObsvRecord::getIsDeleted, CommonConstant.NO_NUMBER)
				.and(wrapper->{
					wrapper.eq(BObsvRecord::getHospitalNumber,hospitalNumber).or().eq(BObsvRecord::getPatientIdent,patientPO.getPatientIdent());
				})
				.isNotNull(BObsvRecord::getPropValue)
				.between(BObsvRecord::getRecTime, startTime, endTime);
		queryWrapper.and(wrapper -> {
			for (String obsvCode : gcxSet) {
				wrapper.or().eq(BObsvRecord::getObsvCode, obsvCode);
			}

		});
		return bObsvRecordMapper.selectList(queryWrapper);
	}


	/**
	 * 获得入科时间列表
	 * 说明：列表值是：入科时间，入科1天（24小时），入科8天，入科16天。。。依次加8 直到出科
	 *
	 * @param apacheiiPickVO 存放中间查询所得的入科时间
	 * @param hospitalNumber 住院号
	 * @return
	 */
	private List<Date> getRkTimeList(ApacheiiPickVO apacheiiPickVO, String hospitalNumber) {
		List<Date> rst = new ArrayList<>();
		List<RkCkInfoOutVO> rkCkList = bHl7MoveDetailMapper.queryLastRkCkTime(systemProperties.getIcuCode(), hospitalNumber);
		if (CollectionUtil.isEmpty(rkCkList)) {
			return Collections.emptyList();
		}
		Date rkDate = rkCkList.get(0).getZrTime();
		apacheiiPickVO.setRkTime(rkDate.getTime());

		if (rkDate == null) {
			return Collections.emptyList();
		}

		Date ckDate = rkCkList.get(0).getZcTime();
		ckDate = ckDate == null ? new Date() : ckDate;
		rst.add(DateUtil.offsetHour(rkDate,  - BEFORE_HOUR));

		long days = DateUtil.betweenDay(rkDate, ckDate, false);
		int count = Convert.toInt(days) / CYCLE;
		int cycle = CYCLE - 1;
		for (int i = 0; i < count; i++) {
			rst.add(DateUtil.offsetDay(rkDate, (i + 1) * cycle));
		}
		return rst;
	}

}
